#include "ObjLoader/inc/ObjLoader.h"
#define TINYOBJLOADER_IMPLEMENTATION
#include "ObjLoader/src/tiny_obj_loader.hpp"
#include <iostream>

ObjLoader::ObjLoader() {
    m_primit_cnt = 0;
    m_primit_vtx_cnt = 0;
    m_location = nullptr;
    m_normal = nullptr;
    m_texutre_cord = nullptr;
}

ObjLoader::~ObjLoader() {}

int ObjLoader::load(const std::string& obj_dir, const std::string& file_name) {
    tinyobj::attrib_t attrs;
    std::vector<tinyobj::shape_t> shapes;
    std::string warn_str, err_str;
    std::string file_path = obj_dir + '/' + file_name;
    bool ret = tinyobj::LoadObj(&attrs, &shapes, nullptr, &warn_str, &err_str, file_path.c_str());
    if(ret == false) {
        std::cout << "warn: " << warn_str << std::endl << "error: " << err_str << std::endl;
        return -1;
    }
    
    m_primit_vtx_cnt = shapes[0].mesh.num_face_vertices.size() * 3;
    m_primit_cnt = shapes[0].mesh.num_face_vertices.size();
    m_location = new float[m_primit_vtx_cnt * 3];
    m_normal = new float[m_primit_vtx_cnt * 3];
    m_texutre_cord = new float[m_primit_vtx_cnt * 2];

    size_t index_offset = 0;
    tinyobj::index_t idx_info;
    size_t location_idx = 0, normal_idx = 0, texture_cord_idx = 0;
    for(size_t face_idx = 0; face_idx < shapes[0].mesh.num_face_vertices.size(); face_idx++) {
        size_t face_vtx_cnt = shapes[0].mesh.num_face_vertices[face_idx];
        for(size_t i = 0; i < face_vtx_cnt; i++) {
            idx_info = shapes[0].mesh.indices[index_offset + i];
            m_location[location_idx++] = attrs.vertices[3 * size_t(idx_info.vertex_index) + 0];
            m_location[location_idx++] = attrs.vertices[3 * size_t(idx_info.vertex_index) + 1];
            m_location[location_idx++] = attrs.vertices[3 * size_t(idx_info.vertex_index) + 2];
            m_normal[normal_idx++] = attrs.normals[3 * size_t(idx_info.normal_index) + 0];
            m_normal[normal_idx++] = attrs.normals[3 * size_t(idx_info.normal_index) + 1];
            m_normal[normal_idx++] = attrs.normals[3 * size_t(idx_info.normal_index) + 2];
            m_texutre_cord[texture_cord_idx++] = attrs.texcoords[2 * size_t(idx_info.texcoord_index) + 0];
            m_texutre_cord[texture_cord_idx++] = attrs.texcoords[2 * size_t(idx_info.texcoord_index) + 1];
        }
        index_offset += face_vtx_cnt;
    }   
    return 0;
}

int ObjLoader::unload() {
    if(m_location != nullptr) {
        delete[] m_location;
    }
    if(m_normal != nullptr) {
        delete[] m_normal;
    }
    if(m_texutre_cord != nullptr) {
        delete[] m_texutre_cord;
    }
    return 0;
}

float* ObjLoader::location() {
    return m_location;
}

float* ObjLoader::normal() {
    return m_normal;
}

float* ObjLoader::texture_cord() {
    return m_texutre_cord;
}

size_t ObjLoader::primitCount() const {
    return m_primit_cnt;
}

size_t ObjLoader::primitVertexCount() const {
    return m_primit_vtx_cnt;
}

